#include "superblock.h"
#include <iostream>
#include <stdio.h>



SuperBlock::SuperBlock(FILE* device) : Block(device, SUPERBLOCK_OFFSET)
{
    superBlock = new super_block_t();
    read(superBlock, sizeof(super_block_t));
}

SuperBlock::~SuperBlock()
{
    delete superBlock;
}

ulong SuperBlock::getInodeSize()
{
    return readUnsignedInteger(superBlock->inodeSize, USHORT);
}

ulong SuperBlock::getVolumeSize()
{
    return readUnsignedInteger(superBlock->volumeSize, UINT);
}

ulong SuperBlock::getFreeListEntries()
{
    return readUnsignedInteger(superBlock->freeListEntries, USHORT);
}

ulong * SuperBlock::getFreeBlockList()
{
    ulong * freeBlockList = new ulong[SUPERBLOCK_FREE_BLOCKLIST_SIZE];

    for(int i = 0; i < SUPERBLOCK_FREE_BLOCKLIST_SIZE; i++)
    {
        freeBlockList[i] = readUnsignedInteger(superBlock->freeBlockList[i], UINT);
    }
    return freeBlockList;
}

ulong SuperBlock::getInodeEntries()
{
    return readUnsignedInteger(superBlock->inodeEntries, USHORT);
}

ulong * SuperBlock::getFreeInodeList()
{
    ulong * freeInodeList = new ulong[SUPERBLOCK_FREE_INODELIST_SIZE];
    for(int i = 0; i < SUPERBLOCK_FREE_INODELIST_SIZE; i++) {
        freeInodeList[i] = readUnsignedInteger(superBlock->freeInodeList[i], USHORT);
    }
    return freeInodeList;
}

bool SuperBlock::getFreeBlockListManipulationLock()
{
    return superBlock->freeBlockListManipulationLock;
}

bool SuperBlock::getInodeListManipulationLock()
{
    return superBlock->inodeListManipulationLock;
}

bool SuperBlock::getModifiedFlag()
{
    return superBlock->modifiedFlag;
}

bool SuperBlock::getReadOnlyFlag()
{
    return superBlock->readOnlyFlag;
}

ulong SuperBlock::getLastUpdate()
{
    return readUnsignedInteger(superBlock->lastUpdate, UINT);
}

char * SuperBlock::getLastUpdateAsString()
{
    time_t epch = getLastUpdate();
    return asctime(gmtime(&epch));
}

ulong SuperBlock::getFreeBlocks()
{
    return readUnsignedInteger(superBlock->freeBlocks, UINT);
}

ulong SuperBlock::getFreeInodes()
{
    return readUnsignedInteger(superBlock->freeInodes, USHORT);
}

ulong SuperBlock::getInterLeaveFactor()
{
    return readUnsignedInteger(superBlock->interLeaveFactor, USHORT);
}

ulong SuperBlock::getCylinderSize()
{
    return readUnsignedInteger(superBlock->cylinderSize, USHORT);
}

unsigned char * SuperBlock::getFileSystemName()
{
    return superBlock->fileSystemName;
}

unsigned char * SuperBlock::getSystemPackName()
{
        return superBlock->systemPackName;
}

//Creates some warnings while compiling, ignore
void SuperBlock::print()
{
    printf("---------------------------------------\n");
    printf("Dump of superblock on %s.%s:\n", getFileSystemName(), getSystemPackName());
    printf("---------------------------------------\n");
    printf("number of blocks in i-list is: %d\n", getInodeSize());
    printf("number of blocks on volume is: %d\n", getVolumeSize());
    printf("number of freeblocks in free[] is: %d (max %d)\n", getFreeListEntries(), SUPERBLOCK_FREE_BLOCKLIST_SIZE);

    printf("blocks: ");
    ulong * freeBlockList = getFreeBlockList();

    for(int i = 0; i < getFreeListEntries(); i++)
    {
        printf("%d ", freeBlockList[i]);
    }
    delete[] freeBlockList;
    printf("\n");

    printf("number of free inodes in inode[] is: %d (max %d)\n", getInodeEntries(), SUPERBLOCK_FREE_INODELIST_SIZE);

    printf("inodes: ");
    ulong * freeInodeList = getFreeInodeList();

    for(int i = 0; i < getInodeEntries(); i++)
    {
        printf("%d ", freeInodeList[i]);
    }
    printf("\n");
    delete[] freeInodeList;

    printf("freelist lock flag %s set\n", getFreeBlockListManipulationLock() == 0 ? "is not" : "is");
    printf("i-list lock flag %s set\n", getInodeListManipulationLock() == 0 ? "is not" : "is");
    printf("superblock %s modified\n", getModifiedFlag() == 0 ? "is not" : "is");
    printf("filesystem %s mounted readonly\n", getReadOnlyFlag() == 0 ? "was not" : "was");
    printf("Last update was %s", getLastUpdateAsString());
    printf("total number of free blocks is: %d \n", getFreeBlocks());
    printf("total number of free inodes is: %d \n", getFreeInodes());
    printf("interleave factors are: %d and %d \n", getInterLeaveFactor(), getCylinderSize());//Where is the upper bound????
    printf("File system name is: %s\n", getFileSystemName());
    printf("File system pack is: %s\n", getSystemPackName());
}
